using System;
using System.IO;
using System.Threading;
using WowAceUpdater.Properties;

namespace WowAceUpdater
{
    internal static class FileSystem
    {
        #region Enums

        internal enum CopyHereOptions
        {
            NoProgressDlg = 4, // Do not display a progress dialog box.  
            RenameIfExists = 8,
            // Give the file being operated on a new name in a move, copy, or rename operation if a file with the target name already exists.  
            YesToAll = 16, // Respond with "Yes to All" for any dialog box that is displayed.  
            EnableUndo = 64, // Preserve undo information, if possible. 
            WildcardOnly = 128, // Perform the operation on files only if a wildcard file name (*.*) is specified.  
            NoProgressFiles = 256, // Display a progress dialog box but do not show the file names.  
            NoConfirmDirCreate = 512,
            // Do not confirm the creation of a new directory if the operation requires one to be created.  
            NoUIOnError = 1024, // Do not display a user interface if an error occurs.  
            NoSecurityAttribs = 2048, // Version 4.71. Do not copy the security attributes of the file. 
            TopDirOnly = 4096, // Only operate in the local directory. Don't operate recursively into subdirectories. 
            NoConnectedFiles = 9182,
            // Version 5.0. Do not copy connected files as a group. Only copy the specified files.  
        }

        #endregion

        #region Constants

        private const string TEMP_DIR_NAME = "WowAceUpdater";

        #endregion

        #region Properties

        public static string TempDirectory
        {
            get { return EnsureDirExists(Path.Combine(Path.GetTempPath(), TEMP_DIR_NAME)); }
        }

        #endregion

        #region Public Methods

        public static void DeleteDirectory(string targetPath)
        {
            if (Settings.Default.UseRecycleBin)
            {
                int rc = NativeMethods.SendToRecycleBin(targetPath);

                if (Directory.Exists(targetPath))
                {
                    Program.LogDbg(
                        string.Format("Failed to delete {0} {1}", targetPath, rc));
                    ForceDeleteDirectory(targetPath);
                }
            }
            else
                ForceDeleteDirectory(targetPath);
        }

        public static string EnsureDirExists(string addonPath)
        {
            try
            {
                if (!Directory.Exists(addonPath))
                    Directory.CreateDirectory(addonPath);
            }
            catch(UnauthorizedAccessException vistafail)
            {
                Program.LogErr(vistafail.ToString());
                MainForm.VistaFail();
                throw;
            }
            return addonPath;
        }

        public static void ForceDeleteDirectory(string targetPath)
        {
            foreach (string dir in Directory.GetDirectories(targetPath))
                ForceDeleteDirectory(dir);

            foreach (string file in Directory.GetFiles(targetPath))
            {
                File.SetAttributes(file, FileAttributes.Normal);
                File.Delete(file);
            }

            // This is weird, but it seems to work if you just come back again later... :)
            int retryCount = 0;
            TryAgain:
            try
            {
                Directory.Delete(targetPath);
            }
            catch
            {
                retryCount++;
                if (retryCount < 5)
                {
                    Thread.Sleep(100);
                    goto TryAgain;
                }
                throw;
            }
        }


        public static bool IsSvnWorkingCopy(string path)
        {
            return IsWorkingCopy(".svn", path);;
        }
        public static bool IsGitWorkingCopy(string path)
        {
            return IsWorkingCopy(".git", path);
        }
        public static bool IsWorkingCopy(string path)
        {
            return IsSvnWorkingCopy(path) || IsGitWorkingCopy(path);
        }
        public static bool IsWorkingCopy(string type, string path)
        {
            if (Directory.Exists(path))
            {
                string[] svnDirs = Directory.GetDirectories(path, ".svn", SearchOption.TopDirectoryOnly);
                return svnDirs.Length > 0;
            }
            return false;
        }

        public static string CheckPathString(string path)
        {
            if (string.IsNullOrEmpty(path))
                return path;

            try
            {
                //string PATH = System.Environment.GetEnvironmentVariable("PATH");

                DirectoryInfo di = new DirectoryInfo(path);

                //if (di.FullName.Contains(Environment.SystemDirectory))
                //    return Environment.GetFolderPath(
                //        Environment.SpecialFolder.MyDocuments);

                return di.FullName;
            }
            catch (Exception e)
            {
                Program.LogDbg(e.ToString());

                return Environment.GetFolderPath(
                    Environment.SpecialFolder.MyDocuments);
            }
        }

        public static bool IsDirectoryProtected(DirectoryInfo i)
        {
            return IsDirectoryProtected(i.FullName);
        }

        public static bool IsDirectoryProtected(string path)
        {
            return ((Settings.Default.SkipSvnWorkingCopies && IsWorkingCopy(path))) ||
                   IsIgnoredAddonDirectory(path);
        }

        public static bool IsIgnoredAddonDirectory(string path)
        {
            return Settings.Default.IgnoredAddons.Contains(Path.GetFileName(path));
        }

        #endregion

        #region Internal Methods

        internal static void UnzipAll(string zipFilePath, string destinationFolder)
        {
            Compression.ExtractZipFile(zipFilePath, destinationFolder);
        }



        #endregion
    }
}